home *** CD-ROM | disk | FTP | other *** search
- /*
- File: Draw n Save.c
-
- Written by: Hiep Dam
- From The Witches' Brew
- starlabs@aol.com
-
- Public domain. Copy, steal, plagiarize mercilessly without
- fear of persecution. As you do, note that any liabilities
- are therefore yours to handle. :-)
-
- Date: August 4 1994
- Version:
- 1.1 Oct 95
- Added provision for saving a file over another file with the
- same name ("replace file?") and added ostype creator argument
- to savepicture...
-
-
- Purpose: Puts up a window, lets you "draw" into the window (press a key to
- exit) and then lets you save your drawing as a standard PICT file. Voila!
- Mostly for beginners.
- */
-
- // ---------------------------------------------------------------------------
-
- void InitToolboxCrud();
- void SavePicture(Handle thePic, OSType creator);
-
- // ---------------------------------------------------------------------------
-
- void main() {
- WindowPtr canvasWindow; // This is the window we'll be drawing into
- PicHandle myPic; // This is the picture we'll stuff our drawing into
- Boolean done = false; // A flag to tell us when we'll be done
- Rect windR; // Rect of the window
- Point mLoc, oldLoc; // Local mouse coords (for our drawing)
- EventRecord theEvent; // Used by GetNextEvent, to tell us when to stop drawing
-
- InitToolboxCrud();
-
- /*
- OK, let's setup some stuff before we can do the "cool" stuff:
- 1) Setup the window
- 2) Setup the graphics environment
- */
- windR = (**GetGrayRgn()).rgnBBox;
- InsetRect(&windR, 50, 50);
- canvasWindow = NewWindow(nil, &windR, "\pCanvas*Press key to end demo.",
- true, documentProc, (WindowPtr)-1, false, 0);
- SetPort(canvasWindow);
-
- // Important to call ClipRect, since upon creation a port's cliprgn's bounds
- // are set wide open (-32,767 to 32,767). Not clipping may result in integer
- // overflow, in which case we might not see a picture at all. In any case
- // a minor but important point.
- ClipRect(&canvasWindow->portRect);
-
- // Tell the Mac OS to begin recording [most] QuickDraw calls from now on,
- // until we call ClosePicture. LineTos, FrameRects, etc. are recorded
- // by the operating system.
- myPic = OpenPicture(&canvasWindow->portRect);
- // By default, calling OpenPicture hides the pen so no drawing is seen.
- // This is contrary to what we want so we'll have to show the pen.
- ShowPen();
-
- // Loop thru and do some fancy-smancy drawing...
- // The code could have been simplified, but this is more efficient
- // in that only changes in the mouse coords are drawn...
-
- // On color macs, we'll draw in blue. Oh joy!
- ForeColor(blueColor);
- do {
- // Is mouse down? If so, time to start recording/drawing
- // our line(s)...
- if (Button()) {
- GetMouse(&mLoc);
- MoveTo(mLoc.h, mLoc.v);
- oldLoc = mLoc;
-
- while (Button()) {
- GetMouse(&mLoc);
- if (oldLoc.h != mLoc.h || oldLoc.v != mLoc.v) {
- LineTo(mLoc.h, mLoc.v); // Actual drawing here
- oldLoc = mLoc;
- }
- }
- }
-
- // Press a key to finish up drawing
- if (GetNextEvent(keyDownMask, &theEvent))
- done = true;
- } while (!done);
- // Restore the color
- ForeColor(blackColor);
-
- // We're done drawing, stop the recording mechanism
- ClosePicture();
-
- // Just to test if we've done things correctly, tell
- // QuickDraw to redraw what we've just recorded...
- EraseRect(&canvasWindow->portRect);
- DrawPicture(myPic, &(**myPic).picFrame);
-
- // Save our newly created picture!
- SavePicture((Handle)myPic, 'Hiep');
-
- // Remember, if you're going to put this stuff in a "real"
- // application, remember to de-allocate the memory taken
- // up by the picture once you're done...
- // (Since we've created the picture via OpenPicture, we
- // call KillPicture. If instead we've gotten our picture
- // via GetPicture, we should instead call ReleaseResource).
- // But note: if we had saved the picture as a 'PICT'
- // resource, we need to use ReleaseResource....
- KillPicture(myPic);
- } // END main
-
- // ---------------------------------------------------------------------------
-
- /*
- This (handy?) little 'ol function saves a picture as a standard "PICT"
- file. Note that barely any error-checking is done; you should add more
- extensive checking for your own application(s). As an excuse for error
- checking, this routine beeps when it encounters one and exits (quite
- ungracefully, too).
-
- A special note concerning PICT files: A pict file is like any other
- "data" file in that you write stuff to the data fork. However, the
- pict file also contains a "special" 512-byte header. Most of the time
- you can ignore this. So when writing to or reading from a pict file,
- just skip the first 512 bytes (i.e. SetFPos(fileRefNum, fsFromStart, 512))
- and all will be well. My experience is that almost all applications
- ignore this 512-byte header (but keep it due to ancient history).
-
- By the way, the code herein is System 7 dependent. If you wish to
- change to System 6 compatibility, you'll have to change the
- StandardFileReply to an SFReply, etc. etc. etc.
- (But why System 6?)
- */
-
- void SavePicture(Handle thePic, OSType creator) {
- StandardFileReply reply;
- OSErr myErr;
- short fileRefNum;
- long picSize; // The size of our picture, give or take a header
-
- // Put up the standard save dialog
- StandardPutFile("\pSave picture into:", "\pMy picture.pict", &reply);
-
- if (reply.sfGood) {
- if (reply.sfReplacing) {
- myErr = FSpDelete(&reply.sfFile);
- if (myErr != noErr) {
- SysBeep(10);
- return;
- }
- }
-
- // Create the file.
- myErr = FSpCreate(&reply.sfFile, creator, 'PICT', reply.sfScript);
- if (myErr != noErr) {
- SysBeep(10);
- return;
- }
-
- // Open it up (the data fork, that is)...
- myErr = FSpOpenDF(&reply.sfFile, fsCurPerm, &fileRefNum);
- if (myErr != noErr) {
- SysBeep(10);
- return;
- }
-
- // Lock up the picture, since it may move when writing to
- // our file. Also get the size of our picture. Then tell
- // the File Manager to allocate enough space in the file
- // for us, keeping in mind the 512-byte header...
- HLock(thePic);
- picSize = GetHandleSize(thePic);
- picSize = picSize + 512;
- myErr = SetEOF(fileRefNum, picSize);
- if (myErr != noErr) {
- SysBeep(10);
- return;
- }
-
- // Alright, time to do the dirty deed (but first,
- // since we don't want to write in the header, tell
- // the File Manager to skip the first 512-bytes)
- myErr = SetFPos(fileRefNum, fsFromStart, 512);
- if (myErr != noErr) {
- SysBeep(10);
- return;
- }
-
- // OK, ok, here we are. Write to the file.
- // Note: FSWrite expects a pointer to our data (i.e. the
- // picture). So we'll have to dereference the
- // picture handle.
- picSize = GetHandleSize(thePic);
- myErr = FSWrite(fileRefNum, &picSize, (Ptr)*thePic);
- if (myErr != noErr) {
- SysBeep(10);
- return;
- }
-
- // Close it up. You may have to call FlushVol() or
- // such to tell the File Manager to write the data
- // to the file immediately (otherwise it waits a
- // while...)
- myErr = FSClose(fileRefNum);
- if (myErr != noErr) {
- SysBeep(10);
- return;
- }
- }
- } // END SavePicture
-
- // ---------------------------------------------------------------------------
-
- // Hey, why don't they put this crap in automagically, like Think Pascal,
- // so us programmers can move on to the more interesting stuff?!?
-
- void InitToolboxCrud() {
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- FlushEvents(everyEvent,0);
- TEInit();
- InitDialogs(0L);
- InitCursor();
- } // END InitToolboxCrud
-
-